# face.py
import os
import base64
import requests
from fastapi import APIRouter, Request, Depends, HTTPException, UploadFile, File, Form,Cookie
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from sqlalchemy import or_
from models import FaceLibrary, FaceInfo, Device, DeviceFaceMapping  # 添加DeviceFaceMapping
from datetime import datetime
from database import get_db
from core.logger import app_logger as logger
from utils import validate_session
from typing import Optional

router = APIRouter()
templates = Jinja2Templates(directory="templates")

# 确保图片存储目录存在
os.makedirs("static/face_images", exist_ok=True)

# 同步相关功能
def create_face_library_http(board_ip: str, library_name: str):
    """通过HTTP创建人脸库"""
    url = f"http://{board_ip}/api/api_repository_create"
    payload = {"albumName": library_name}
    try:
        response = requests.post(url, json=payload, timeout=5)
        logger.debug(f"创建人脸库: {url} status_code:{response.status_code}")
        if response.status_code == 200:
            result = response.json()
            logger.debug(f"创建结果: {result}")
            if result.get("Result", {}).get("Code") == 0:
                return True
        return False
    except Exception as e:
        logger.error(f"设备 {board_ip} 创建人脸库失败: {str(e)}")
        return False

def check_face_library_exist(board_ip: str, library_name: str) -> bool:
    """检查设备上是否存在指定名称的人脸库"""
    url = f"http://{board_ip}/api/api_repository_info"
    payload = {"albumName": library_name}
    try:
        response = requests.post(url, json=payload, timeout=5)
        logger.debug(f"查询人脸库: {url} status_code:{response.status_code}")
        if response.status_code == 200:
            result = response.json()
            logger.debug(f"查询结果: {result}")
            # 检查返回结果中是否有匹配的人脸库
            if result.get("Result", {}).get("Code") == 0:
                for library in result.get("data", []):
                    if library.get("albumName") == library_name:
                        return True
        return False
    except Exception as e:
        logger.error(f"设备 {board_ip} 查询人脸库失败: {str(e)}")
        return False

def register_face_http(user_id: str,board_ip: str, library_name: str, user_name: str, image_path: str):
    """通过HTTP注册人脸"""
    url = f"http://{board_ip}/api/api_register_face"
    
    # 读取图片并转换为base64
    with open(image_path, "rb") as image_file:
        image_base64 = base64.b64encode(image_file.read()).decode('utf-8')
    
    payload = {
        "albumName": library_name,
        "name": user_id,
        "image": image_base64,
        "realName":user_name
    }
    logger.debug(f"传的数据{payload}")
    try:
        response = requests.post(url, json=payload, timeout=10)
        if response.status_code == 200:
            result = response.json()
            # logger.debug(f"传的数据{result}")
            result_code = result.get("Result", {}).get("Code")
            # 成功注册
            if result_code == 0:
                return result.get("photoId")
            # 人脸已存在
            elif result_code == 2001:  # 假设2001是人脸已存在的错误码
                return "FACE_EXIST"
        return None
    except Exception as e:
        logger.error(f"设备 {board_ip} 注册人脸失败: {str(e)}")
        return None

def delete_face_http(board_ip: str, library_name: str, photo_id: str):
    """通过HTTP注销人脸"""
    url = f"http://{board_ip}/api/api_face_delete"
    payload = {
        "albumName": library_name,
        "photoId": photo_id
    }
    
    try:
        response = requests.post(url, json=payload, timeout=5)
        if response.status_code == 200:
            result = response.json()
            if result.get("Result", {}).get("Code") == 0:
                return True
        return False
    except Exception as e:
        logger.error(f"设备 {board_ip} 注销人脸失败: {str(e)}")
        return False

def sync_face_to_device(face_info: FaceInfo, library_name: str, db: Session):
    """将单个人脸同步到所有设备 - 智能处理人脸库已存在的情况"""
    devices = db.query(Device).filter(Device.DeadTime == None).all()
    if not devices:
        return "没有可用的设备"
    
    results = []
    for device in devices:
        # 1. 检查人脸库是否存在
        library_exists = check_face_library_exist(device.BoardIp, library_name)
        
        if not library_exists:
            # 2. 如果人脸库不存在，则创建
            if create_face_library_http(device.BoardIp, library_name):
                results.append(f"设备 {device.BoardIp} 创建人脸库成功")
            else:
                results.append(f"设备 {device.BoardIp} 创建人脸库失败")
                continue  # 创建失败，跳过该设备的后续注册
        
        # 3. 注册人脸
        photo_id = register_face_http(face_info.UserId,device.BoardIp, library_name, face_info.UserName, face_info.ImagePath)
        if photo_id == "FACE_EXIST":
            # 人脸已存在
            results.append(f"设备 {device.BoardIp} 人脸已存在")
        elif photo_id:
            # 保存映射关系到新表
            mapping = DeviceFaceMapping(
                FaceId=face_info.FaceId,
                DeviceId=device.DeviceId,
                PhotoId=photo_id,
                LibraryName=library_name
            )
            db.add(mapping)
            db.commit()
            results.append(f"设备 {device.BoardIp} 同步成功 (photoId: {photo_id})")
        else:
            results.append(f"设备 {device.BoardIp} 该人脸已注册")
    
    return "<br>".join(results)

def sync_delete_face_to_device(face_info: FaceInfo, library_name: str, db: Session):
    """将单个人脸从所有设备注销"""
    # 获取所有设备映射关系
    mappings = db.query(DeviceFaceMapping).filter(
        DeviceFaceMapping.FaceId == face_info.FaceId,
        DeviceFaceMapping.DeadTime == None
    ).all()
    
    if not mappings:
        return "没有找到设备映射记录"
    
    results = []
    for mapping in mappings:
        device = db.query(Device).filter(Device.DeviceId == mapping.DeviceId).first()
        if not device:
            results.append(f"找不到设备ID: {mapping.DeviceId}")
            continue
            
        # 1. 检查人脸库是否存在
        if not check_face_library_exist(device.BoardIp, mapping.LibraryName):
            results.append(f"设备 {device.BoardIp} 人脸库不存在")
            continue
        
        # 2. 注销人脸
        if delete_face_http(device.BoardIp, mapping.LibraryName, mapping.PhotoId):
            # 硬删除映射关系（直接删除记录）
            db.delete(mapping)
            db.commit()
            results.append(f"设备 {device.BoardIp} 注销成功 (photoId: {mapping.PhotoId})")
        else:
            results.append(f"设备 {device.BoardIp} 注销失败")
    
    return "<br>".join(results)

# 路由处理
@router.get("/face", response_class=HTMLResponse)
async def face_management(
    request: Request, 
    SessionId: Optional[str] = Cookie(None),
    UserName: Optional[str] = Cookie(None),
    db: Session = Depends(get_db),
    search: str = None,
    success: str = None,
    error: str = None,
    sync_result: str = None
):
    if not SessionId or not UserName or not validate_session(SessionId, UserName):
        return RedirectResponse(url="/")
    
    # 构建查询
    query = db.query(FaceInfo)\
        .filter(FaceInfo.DeadTime == None)
    
    # 如果有搜索词，添加模糊查询条件
    if search:
        # 在多个字段上进行模糊查询
        query = query.filter(
            or_(
                FaceInfo.UserId.ilike(f"%{search}%"),
                FaceInfo.UserName.ilike(f"%{search}%"),
                FaceInfo.Gender.ilike(f"%{search}%")
            )
        )
    
    faces_db = query.all()
    
    face_list = []
    current_year = datetime.now().year
    for face_info in faces_db:
        # 计算年龄
        if face_info.BirthYear:
            age = current_year - face_info.BirthYear
        else:
            age = "未知"
        face_dict = face_info.to_dict()
        face_dict["Age"] = age
        
        face_list.append(face_dict)
    
    return templates.TemplateResponse("face.html", {
        "request": request, 
        "faces": face_list,
        "current_year": current_year,
        "success": success,
        "error": error,
        "sync_result": sync_result
    })

@router.get("/registerface", response_class=HTMLResponse)
async def register_face_form(request: Request, db: Session = Depends(get_db)):
    current_year = datetime.now().year
    return templates.TemplateResponse("registerface.html", {
        "request": request, 
        "current_year": current_year
    })

@router.post("/registerface")
async def register_face(
    request: Request,
    user_id: str = Form(...),
    user_name: str = Form(...),
    birth_year: int = Form(...),
    gender: str = Form(...),
    image: UploadFile = File(...),
    db: Session = Depends(get_db)
):
    # 验证出生年份
    current_year = datetime.now().year
    if birth_year < 1900 or birth_year > current_year:
        return RedirectResponse(
            url=f"/face?error=出生年份必须在1900-{current_year}之间", 
            status_code=303
        )
    
    # 验证性别
    if gender not in ["男", "女"]:
        return RedirectResponse(
            url="/face?error=性别必须为'男'或'女'", 
            status_code=303
        )
    
    # 固定使用"美佳"人脸库
    library_name = "美佳"
    library = db.query(FaceLibrary).filter(
        FaceLibrary.LibraryName == library_name, 
        FaceLibrary.DeadTime == None
    ).first()
    
    if not library:
        # 创建美佳人脸库
        library = FaceLibrary(LibraryName=library_name)
        db.add(library)
        db.commit()
        db.refresh(library)
    
    library_id = library.LibraryId

    # 保存图片
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
    file_path = f"static/face_images/{user_id}_{timestamp}.jpg"
    with open(file_path, "wb") as buffer:
        buffer.write(await image.read())

    # 创建人脸记录
    face_info = FaceInfo(
        UserId=user_id,
        UserName=user_name,
        BirthYear=birth_year,
        Gender=gender,
        LibraryId=library_id,
        ImagePath=file_path
    )
    db.add(face_info)
    db.commit()
    db.refresh(face_info)

    # 注册时自动同步到设备
    sync_result = sync_face_to_device(face_info, library_name, db)

    # 重定向到管理页面
    return RedirectResponse(
        url=f"/face?success=人脸注册成功&sync_result={sync_result}", 
        status_code=303
    )

@router.post("/delete-face/{face_id}")
async def delete_face(face_id: int, db: Session = Depends(get_db)):
    try:
        # 获取人脸记录
        face = db.query(FaceInfo).filter(FaceInfo.FaceId == face_id).first()
        if not face:
            return RedirectResponse(
                url=f"/face?error=人脸记录不存在", 
                status_code=303
            )
        
        # 获取关联的人脸库名称（用于注销操作）
        library = db.query(FaceLibrary).filter(FaceLibrary.LibraryId == face.LibraryId).first()
        library_name = library.LibraryName if library else "美佳"
        
        # 执行注销操作：将人脸从所有设备注销
        sync_delete_result = sync_delete_face_to_device(face, library_name, db)
        
        # 删除本地图片文件
        image_path = face.ImagePath
        if os.path.exists(image_path):
            try:
                os.remove(image_path)
                logger.info(f"删除图片文件成功: {image_path}")
            except Exception as e:
                logger.error(f"删除图片文件失败: {image_path}, {str(e)}")
        
        # 硬删除所有相关设备映射记录（不再使用软删除）
        db.query(DeviceFaceMapping).filter(DeviceFaceMapping.FaceId == face_id).delete()
        
        # 软删除人脸记录
        face.DeadTime = datetime.now()
        
        db.commit()
        
        # 重定向回人脸管理页面，显示成功消息
        return RedirectResponse(
            url=f"/face?success=人脸删除成功（包括本地图片和设备注销）", 
            status_code=303
        )
    except Exception as e:
        logger.error(f"删除人脸时出错: {str(e)}")
        return RedirectResponse(
            url=f"/face?error=删除失败: {str(e)}", 
            status_code=303
        )

@router.post("/sync-face/{face_id}")
async def sync_face_to_devices(
    face_id: int,
    db: Session = Depends(get_db)
):
    """将单个人脸同步到所有设备"""
    # 获取人脸信息
    face_info = db.query(FaceInfo).filter(FaceInfo.FaceId == face_id).first()
    if not face_info:
        return RedirectResponse(
            url=f"/face?error=人脸记录不存在", 
            status_code=303
        )
    
    # 获取关联的人脸库
    library = db.query(FaceLibrary).filter(FaceLibrary.LibraryId == face_info.LibraryId).first()
    if not library:
        return RedirectResponse(
            url=f"/face?error=关联的人脸库不存在", 
            status_code=303
        )
    
    # 同步到所有设备
    sync_result = sync_face_to_device(face_info, library.LibraryName, db)
    
    # 重定向回人脸管理页面，显示同步结果
    return RedirectResponse(
        url=f"/face?sync_result={sync_result}", 
        status_code=303
    )